package p3.ejemplos;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.BindException;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JFrame;

import p3.IServidor;

public class ServidorFicheros extends JFrame implements ActionListener, Runnable {
	
	private static final long serialVersionUID = 5636964816537805682L;
	
	public static final int ModoIterativo = 1;
	public static final int ModoConcurrente = 2;
	public static final int ModoPooled = 3;


	protected int listenPort = 3000;
	int modo = ModoIterativo;
	int nuevoModo = ModoIterativo;
	
	IServidor currentServer;
	
	
	JButton btClose, btIterativo, btConcurrente, btPooled;
	JLabel lbMode;

	
	/**
	 * Crea servidor iterativo
	 */
	public ServidorFicheros(){
		super("Servidor Ficheros");
		
		btClose = new JButton("Close Server");
		btClose.addActionListener(this);
		btIterativo = new JButton("Servicio Iterativo");
		btIterativo.addActionListener(this);
		btConcurrente = new JButton("Hilo por petición");
		btConcurrente.addActionListener(this);
		btPooled = new JButton("Pila de Hilos");
		btPooled.addActionListener(this);
		
		lbMode = new JLabel(getModeDescription(modo));
		
		getContentPane().setLayout(new GridLayout(5,1));
		getContentPane().add(btIterativo);
		getContentPane().add(btConcurrente);
		getContentPane().add(btPooled);
		getContentPane().add(btClose);
		getContentPane().add(lbMode);
		
		setSize (200,240);
		setVisible(true);  
		validate();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 	
		
		addWindowListener(
				new WindowAdapter(){
					public void windowClosing(WindowEvent e){
						shutdown();
					}
				}
		);
		
		// Manejador Iterativo.
		currentServer = new ServidorIterativo();
		
		// Se pone a la espera de peticiones de servicio.
		new Thread(this).start();
		
	}
	
	public void run(){
		aceptarConexiones();
	}
	
	
	public void actionPerformed(ActionEvent ae){
		if (ae.getSource() == btClose){
			System.out.println("Closing server");
			currentServer.shutdown();
			return;
		}
		if (ae.getSource() == btIterativo){
			nuevoModo = ServidorFicheros.ModoIterativo;   
			if (modeHasChanged()){
				changeMode();
			    new Thread(this).start();
			}
			return;
			
		}
		if (ae.getSource() == btConcurrente){
			nuevoModo = ServidorFicheros.ModoConcurrente;   
			if (modeHasChanged()){
				changeMode();
			    new Thread(this).start();
			}
			return;
		}
		if (ae.getSource() == btPooled){
			nuevoModo = ServidorFicheros.ModoPooled;    
			if (modeHasChanged()){
				changeMode();
			    new Thread(this).start();
			}
			return;
        }
	}
	
	private void changeMode(){
		System.out.println("actionPerformed: changing mode to: " + nuevoModo);
		modo = nuevoModo;
		currentServer.shutdown();
		currentServer = getServer(modo);
		System.out.println("actionPerformed: Modo: " + getModeDescription(modo));
		lbMode.setText(getModeDescription(nuevoModo));
	}
	
	
	/**
	 * Cierra el socket servidor.
	 */
	private void shutdown(){
		currentServer.shutdown();
	}
	
	/**
	 * Crea el socket servidor y se pone a la espera de peticiones de servicio.
	 * Cuando llega una petición de servicio la sirve y al terminar el servicio 
	 * ejecuta la siguiente o se pone a la espera si no hay ninguna petición
	 * pendiente.
	 */
	public void aceptarConexiones() {
		System.out.println("Aceptar conexiones. Modo: " + getModeDescription(modo));

		try {
			currentServer.aceptarConexiones();
		} catch (BindException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("Aceptar conexiones. Exit...: ");
	}
	
	private boolean modeHasChanged(){
		return (modo != nuevoModo);
	}
		
	private IServidor getServer(int modo){
		IServidor server = null;
		switch(modo){
		case ServidorFicheros.ModoIterativo: 
			System.out.println("getHandler: ModoIterativo");
			server = new ServidorIterativo();
			break;
		case ServidorFicheros.ModoConcurrente:
			System.out.println("getHandler: ModoConcurrente");
			server = new ServidorConcurrente(); 
			break;
		case ServidorFicheros.ModoPooled: 
			System.out.println("getHandler: ModoPooled");			
			server = new ServidorPilaDeHilos(); 
			break;
		default:
			System.out.println("Unsupported mode");
		}
		return server;
	}
	
	private String getModeDescription(int mode){
		String s = new String();
		switch(mode){
		case ServidorFicheros.ModoIterativo: s = "Modo Iterativo"; 
		break;
		case ServidorFicheros.ModoConcurrente: s = "Modo Concurrente"; 
		break;
		case ServidorFicheros.ModoPooled: s = "Modo Pila de Hilos"; 
		break;
		default:break;
		}
		return s;
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
       new ServidorFicheros();       
	}
}
